/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 bitmap_layer.h

	$Header: /resource_editor/alpha_blend.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined(ALPHA_BLEND_H_INCLUDED)
#define ALPHA_BLEND_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "convert_16_bit.h"

// --------------------------------------------------------
// inlined alpha blending routines
// --------------------------------------------------------

inline int alpha_blend16(int dest , int source, int alpha)
{
	if (!alpha)
		return dest;
	else
	{
		alpha += (alpha&0x8)>>3;
		
		return 
			( ( ((((source & g_red_blue_16_bit_mask)- (dest & g_red_blue_16_bit_mask)) * alpha)  +   ((dest & g_red_blue_16_bit_mask) << 4))	& g_red_blue_16_bit_mask_shifted)
			+ ( ((((source & g_green_16_bit_mask)	- (dest & g_green_16_bit_mask)) * alpha)     +   ((dest & g_green_16_bit_mask) << 4))		& g_green_16_bit_mask_shifted)
			) >> 4;
	}
}

inline int alpha_1( int pixel )
{
	return ( pixel & g_alpha_16th_mask ) >> 4;
}

inline int alpha_2( int pixel )
{
	return ( pixel & g_alpha_8th_mask ) >> 3;
}

inline int alpha_4( int pixel )
{
	return ( pixel & g_alpha_4th_mask ) >> 2;
}

inline int alpha_8( int pixel )
{
	return ( pixel & g_alpha_half_mask ) >> 1;
}

inline int alpha_blend16_ref( int dest, int source, int alpha )
{
	// in each case, add two values, resulting in 16 total points.
	switch (alpha)
	{
		case 0:
			return dest;
		case 1:
			return dest - alpha_1( dest ) + alpha_1( source );      
		case 2:
            return dest - alpha_2( dest ) + alpha_2( source );
		case 4:
            return dest - alpha_4( dest ) + alpha_4( source );
		case 8:
            return dest - alpha_8(dest) + alpha_8( source );
		case 11:
            return source - alpha_4(source) + alpha_4( dest );
		case 13:
            return source - alpha_2(source) + alpha_2( dest );
		case 14:
			return source - alpha_1(source) + alpha_1( dest );      
		case 9:
		case 10:
		case 12:
		{
			alpha++;
			int dest_alpha = 16 - alpha;

			return ((((source & g_blue_16_bit_mask) * alpha
				    + (dest & g_blue_16_bit_mask) * dest_alpha) & g_blue_16_bit_mask_shifted)
 				  + (((source & g_green_16_bit_mask) * alpha
				    + (dest & g_green_16_bit_mask) * dest_alpha) & g_green_16_bit_mask_shifted)
				  + (((source & g_red_16_bit_mask) * alpha 
				    + (dest & g_red_16_bit_mask) * dest_alpha) & g_red_16_bit_mask_shifted)) >> 4;
		}
		case 3:
		case 5:
		case 6:
		case 7:
		{
			int dest_alpha = 16 - alpha;

			return ((((source & g_blue_16_bit_mask) * alpha
				    + (dest & g_blue_16_bit_mask) * dest_alpha) & g_blue_16_bit_mask_shifted)
 				  + (((source & g_green_16_bit_mask) * alpha
				    + (dest & g_green_16_bit_mask) * dest_alpha) & g_green_16_bit_mask_shifted)
				  + (((source & g_red_16_bit_mask) * alpha 
				    + (dest & g_red_16_bit_mask) * dest_alpha) & g_red_16_bit_mask_shifted)) >> 4;
		}
		case 15:
			return source;
	}
	return source;
}

// multiply two alpha numbers from 0-15, and divide by 15
inline int multiply_alpha16( int left, int right )
{
	// in each case, add two values, resulting in 16 total points.
	return left * right / 15;
}

#endif // ALPHA_BLEND_H_INCLUDED